
using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;

//svnkit imports
using org.tmatesoft.svn.core;
using org.tmatesoft.svn.core.wc;

namespace Subsync.Core.Subversion
{
	/// <summary>
	/// SVN Checkout
	/// </summary>
	public class SVNCheckout : CommandBase
	{

		/// <summary>
		/// We have our variables declared here.
		/// Access modifiers as you can observe, is public. Why?
		/// Because we trust our programmers.
		/// 
		/// Try to be verbose with the variable names.
		/// Also, try to include *sane defaults*. Take peg_revision for eg.
		/// </summary>
	
		public SVNURL checkout_url;
		public java.io.File destination_path;
		public SVNRevision peg_revision = SVNRevision.UNDEFINED;
		public SVNRevision revision = SVNRevision.HEAD;
		public SVNDepth depth = SVNDepth.INFINITY; //infinity means recursive
		public bool allow_unversioned_obstructions = true;
		
		/// <summary>
		/// Sane default constructor.
		/// </summary>
		/// <param name="checkout_url">
		/// A <see cref="System.String"/>
		/// </param>
		public SVNCheckout(string checkout_url) {
			//DEBUG MSG. *Always* include this.
			Debug.WriteLine("SVN Checkout minimal Constructor with sane defaults");
			lazyCheckout(checkout_url);
		}
		
		/// <summary>
		/// Full constructor for Checkout.
		/// </summary>
		/// <param name="checkout_url_str">
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="dest_path">
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="peg_rev">
		/// A <see cref="SVNRevision"/>
		/// </param>
		/// <param name="co_rev">
		/// A <see cref="SVNRevision"/>
		/// </param>
		/// <param name="depth">
		/// A <see cref="SVNDepth"/>
		/// </param>
		/// <param name="allow_unv_obs">
		/// A <see cref="System.Boolean"/>
		/// </param>
		public SVNCheckout(string checkout_url_str,string dest_path,
		                   SVNRevision peg_rev, SVNRevision co_rev,
		                   SVNDepth depth, Boolean allow_unv_obs) 
		{
			//DEBUG MSG. *Always* include this.
			Debug.WriteLine("SVN Checkout normal Constructor");
			
			this.checkout_url = SVNURL.parseURIEncoded(checkout_url_str);
			this.destination_path = new java.io.File(dest_path);
			this.peg_revision = peg_rev;
			this.revision = co_rev;
			this.depth = depth;
			this.allow_unversioned_obstructions = allow_unv_obs;
		}
		
		public void lazyCheckout(string checkout_url) {
			//for auto appending. creating sane default.
			//ie: http://blabla.com/svn/trunk/dev will checkout the folder into <current_dir>/dev
			string[] url_split = checkout_url.Split('/');
			
			this.checkout_url = SVNURL.parseURIEncoded(checkout_url);
			this.destination_path = new java.io.File(Path.Combine(Directory.GetCurrentDirectory(),url_split[url_split.Length-1]));
		}
		
		/// <summary>
		/// Execute SVN Checkout
		/// </summary>
		public override void Execute ()
		{
			//DEBUG MSG. *Always* include this.
			Debug.WriteLine("SVN Checkout Execution");
			
			//library setup
			Tools.setupLibrary();
			
			//load up the clients
			SVNClientManager cm = SVNClientManager.newInstance();
			SVNUpdateClient uc = cm.getUpdateClient();
						
			try {
				uc.doCheckout(this.checkout_url, this.destination_path, 
				              this.peg_revision, this.revision, this.depth, 
				              this.allow_unversioned_obstructions);						
			}
			catch (SVNException e) {
				//we convert this exception to a non SVNKit exception.
				//we want to minimize interfacing with SVNkit outside of this namespace (abstraction)
				throw new SVNExecuteException(e.getMessage());
			}
		}
		
		public override Dictionary<string, List<object>> getTokens ()
		{
			Dictionary<string, List<object>> ret = new Dictionary<string, List<object>> ();
			ret.Add("checkout",new List<object>() {"co","checkout"});
			return ret;
		}
		
		public override List<KeyValuePair<string,initPointer>> getInitPointers() {
			List<KeyValuePair<string,initPointer>> ret = new List<KeyValuePair<string,initPointer>>();
			ret.Add(new KeyValuePair<string,initPointer>("checkout",new initPointer(this.handleCLI)));
			return ret;
		}
		
		public void handleCLI(Dictionary<string,List<object>> tokens) {
			if (tokens["checkout"].Count != 1) {
				Console.WriteLine("Not enough arguments: Checkout requires at least 1 argument (url)");
				return;
			}
			string url = (string) tokens["checkout"][0];
			this.lazyCheckout(url);
			this.Execute();
		}
		
		public SVNCheckout() {
			
		}

	}
}




